/*--------------------------------------------------------------------------------------------------
Yatak Operation System Project Copyright 2012
Author : Ilya Churaev
Started : 5 Oct 2012		Updated : 6 Mar 2013
File Name : ps.c		Purpose : Function for show process
--------------------------------------------------------------------------------------------------*/
#include <yatak/yatak.h>
#include <screen.h>
#include <sched.h>
#include <shell.h>
#include <users.h>

extern volatile task_t *current_task;
extern volatile task_t *ready_queue;
static int count = 0;

void PrintT (thread_t * tmp, int level)
{
	int i;
	while (tmp)
	{
		for (i = 0; i < level-1; i++)
			kprintf ("  ");
		if (i < level)
			kprintf ("||-");
		if (level < 3)
			kprintf ("%s",tmp->parent->name);
		set_csr (25, GetYCoord ());
		kprintf ("%d",(int)tmp->tid);
		set_csr (32, GetYCoord ());
		if (tmp->prio == PRIO_IDLE)
			kprintf ("IDLE");
		else if (tmp->prio == PRIO_LOW)
			kprintf ("LOW");
		else if (tmp->prio == PRIO_NORMAL)
			kprintf ("NORM");
		else if (tmp->prio == PRIO_HIGH)
			kprintf ("HIGH");
		else if (tmp->prio == PRIO_DEAD)
			kprintf ("DEAD");
		set_csr (40, GetYCoord ());
		if (!tmp->terminal)
			kprintf ("?");
		else
			kprintf ("%s",tmp->terminal->name);
		set_csr (48, GetYCoord ());
		kprintf ("0x%x",tmp);
		set_csr (60, GetYCoord ());
		if (tmp->state == TASK_RUNNING)
			 kprintf ("R");
		else if (tmp->state == TASK_WAITING)
			kprintf ("W");
		else if (tmp->state == TASK_STOPPED)
			kprintf ("St");
		else if (tmp->state == TASK_SLEEPING)
			kprintf ("Sl");
		else
			kprintf ("Unknown");
		
		set_csr (69, GetYCoord ());
		kprintf ("%s",FindUserName (tmp->parent->uid));
		kprintf ("\n");
		tmp = tmp->next;
	}
}

void Print (task_t * tmp, int level)
{
	int i;
	count++;
	for (i = 0; i < level-1; i++)
		kprintf ("  ");
	if (i < level)
		kprintf ("|-");
	kprintf ("%s",tmp->name);
	set_csr (25, GetYCoord ());
	kprintf ("%d",(int)tmp->pid);
	set_csr (32, GetYCoord ());
	if (tmp->threads->prio == PRIO_IDLE)
		kprintf ("IDLE");
	else if (tmp->threads->prio == PRIO_LOW)
		kprintf ("LOW");
	else if (tmp->threads->prio == PRIO_NORMAL)
		kprintf ("NORM");
	else if (tmp->threads->prio == PRIO_HIGH)
		kprintf ("HIGH");
	else if (tmp->threads->prio == PRIO_DEAD)
		kprintf ("DEAD");
	set_csr (40, GetYCoord ());
	if (!tmp->threads->terminal)
		kprintf ("?");
	else
		kprintf ("%s",tmp->threads->terminal->name);
	set_csr (48, GetYCoord ());
	kprintf ("0x%x",tmp);
	set_csr (60, GetYCoord ());
	if (tmp->state == TASK_RUNNING)
		 kprintf ("Run");
	else if (tmp->state == TASK_WAITING)
		kprintf ("Wait");
	else if (tmp->state == TASK_STOPPED)
		kprintf ("Stop");
	else if (tmp->state == TASK_SLEEPING)
		kprintf ("Sleep");
	else
		kprintf ("Unknown");
	
	set_csr (69, GetYCoord ());
	kprintf ("%s",FindUserName (tmp->uid));
	kprintf ("\n");
		
	if (tmp->threads->next)
		PrintT (tmp->threads, level + 2);
	if (tmp->child)
		Print (tmp->child, level + 1);
	if (tmp->brother)
		Print (tmp->brother, level);	
}

void ps ()
{
	unsigned int flags;
	save_flags (flags);
	cli();
	kprintf ("================================================================================");
	set_csr (0, GetYCoord ());
	kprintf ("Name:");
	set_csr (25, GetYCoord ());
	kprintf ("ID:");
	set_csr (32, GetYCoord ());
	kprintf ("Prio:");
	set_csr (40, GetYCoord ());
	kprintf ("TTY:\t");
	set_csr (48, GetYCoord ());
	kprintf ("Address:");
	set_csr (60, GetYCoord ());
	kprintf ("State:");
	set_csr (69, GetYCoord ());
	kprintf ("User:");
	
	kprintf ("\n");
	task_t * tmp = current_task;
	while (tmp->parent) tmp = tmp->parent;
	if (tmp)
	{
		count = 0;
		Print (tmp, 0);
	}
	else
		kprintf ("NULL\n");
	kprintf ("Number of process: %d\n", count);
	kprintf ("================================================================================");
	restore_flags(flags);
}
